#include "BloomProcess.h"
#include "Utils/LogUtil.h"
#include "Render/RenderState.h"
#include "Core/CoreGlobals.h"
#include "Game/Scene/Entity.h"
#include "Game/Component/Model.h"
#include "Render/Buffer/VertexBuffer.h"
#include "Render/Buffer/IndexBuffer.h"
#include "Render/Buffer/CustomBuffer.h"


void BloomProcess::OnInit()
{
	ENQUEUE_RENDER_COMMAND(BuildModel)([this](VkCommandBuffer commandBuffer)
		{

			// Hor bloom

			mSampler = RHISampler::Builder()
				.SetAddressModeU(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
				.SetAddressModeV(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
				.SetAddressModeW(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
				.SetBorderColor(VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE)
				.Build();

			RefCountPtr<RHITexture> colorRenderTarget0 = GetTexture("SkyboxProcess", "ColorRenderTarget0");
			RefCountPtr<RHITexture> colorRenderTarget1 = GetTexture("SkyboxProcess", "ColorRenderTarget1");

			RHIDescriptor::Builder horDescriptorBuilder;
			mHorBloomFragmentShader = horDescriptorBuilder.AddShader<BloomFragmentShader>();
			mHorBloomFragmentShader->dir->SetVaule(0);

			mHorDescriptor = horDescriptorBuilder
				.PushShader<BloomVertexShader>()
				.SetDescriptorCount(0, 1, true)
				.Build();

			mHorDescriptor->SetValue("samplerColor0", colorRenderTarget0, mSampler);
			mHorDescriptor->SetValue("samplerColor1", colorRenderTarget1, mSampler);
			mHorDescriptorMask = mHorDescriptor->AllocateDescriptor();

			mHorColorRenderTarget = ColorRenderTarget::Builder()
				.SetUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)
				.SetStoreOp(VK_ATTACHMENT_STORE_OP_STORE)
				.SetFinalLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
				.SetMultiple(true)
				.Build();

			mHorPipeline = GraphicsPipeline::Builder()
				.SetDescriptor(mHorDescriptor)
				.AddColorRenderTarget(mHorColorRenderTarget)
				.SetDstStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)
				.SetDstAccessMask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
				.SetSrcStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)
				.SetSrcAccessMask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
				.Build();

			mHorRenderPass = RHIRenderPass::Builder()
				.AddRenderTarget(mHorColorRenderTarget)
				.AddPipeline(mHorPipeline)
				.SetSrcStageMask(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)
				.SetSrcAccessMask(VK_ACCESS_SHADER_READ_BIT)
				.SetDstStageMask(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)
				.SetDstAccessMask(VK_ACCESS_SHADER_READ_BIT)
				.Build();

			mHorFrameBuffer = RHIFrameBuffer::Builder()
				.SetRenderPass(mHorRenderPass)
				.Build();




			// Ver bloom




			RHIDescriptor::Builder verDescriptorBuilder;
			mVerBloomFragmentShader = verDescriptorBuilder.AddShader<BloomFragmentShader>();
			mVerBloomFragmentShader->dir->SetVaule(1);

			mVerDescriptor = verDescriptorBuilder
				.PushShader<BloomVertexShader>()
				.SetDescriptorCount(0, 1, true)
				.Build();

			mVerDescriptor->SetValue("samplerColor0", colorRenderTarget0, mSampler);
			mVerDescriptor->SetValue("samplerColor1", mHorColorRenderTarget, mSampler);
			mVerDescriptorMask = mVerDescriptor->AllocateDescriptor();

			mVerColorRenderTarget = ColorRenderTarget::Builder()
				.SetUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)
				.SetStoreOp(VK_ATTACHMENT_STORE_OP_STORE)
				.SetFinalLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
				.SetMultiple(true)
				.Build(this, "ColorRenderTarget");

			mVerPipeline = GraphicsPipeline::Builder()
				.SetDescriptor(mVerDescriptor)
				.AddColorRenderTarget(mVerColorRenderTarget)
				.SetDstStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)
				.SetDstAccessMask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
				.SetSrcStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)
				.SetSrcAccessMask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
				.Build();

			mVerRenderPass = RHIRenderPass::Builder()
				.AddRenderTarget(mVerColorRenderTarget)
				.AddPipeline(mVerPipeline)
				.SetSrcStageMask(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)
				.SetSrcAccessMask(VK_ACCESS_SHADER_READ_BIT)
				.SetDstStageMask(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)
				.SetDstAccessMask(VK_ACCESS_SHADER_READ_BIT)
				.Build();

			mVerFrameBuffer = RHIFrameBuffer::Builder()
				.SetRenderPass(mVerRenderPass)
				.Build();

		});
}

void BloomProcess::OnTick(float deltaTime)
{
	ENQUEUE_RENDER_COMMAND(RecordCommand)([this](VkCommandBuffer commandBuffer)
		{
			VkRenderPassBeginInfo renderPassBeginInfo = mHorFrameBuffer->GetRenderPassBeginInfo();

			vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);

			vkCmdSetViewport(commandBuffer, 0, 1, &GRenderState->GetViewport());
			vkCmdSetScissor(commandBuffer, 0, 1, &GRenderState->GetScissor());

			vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, mHorPipeline->GetPipeline());

			vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, mHorPipeline->GetPipelineLayout(), 0, 1, &mHorDescriptorMask.GetDescriptorSet(), 0, nullptr);

			vkCmdDraw(commandBuffer, 3, 1, 0, 0);

			vkCmdEndRenderPass(commandBuffer);





			renderPassBeginInfo = mVerFrameBuffer->GetRenderPassBeginInfo();

			vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);

			vkCmdSetViewport(commandBuffer, 0, 1, &GRenderState->GetViewport());
			vkCmdSetScissor(commandBuffer, 0, 1, &GRenderState->GetScissor());

			vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, mVerPipeline->GetPipeline());

			vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, mVerPipeline->GetPipelineLayout(), 0, 1, &mVerDescriptorMask.GetDescriptorSet(), 0, nullptr);

			vkCmdDraw(commandBuffer, 3, 1, 0, 0);

			vkCmdEndRenderPass(commandBuffer);
		});
}

void BloomProcess::OnResize()
{
	RefCountPtr<RHITexture> colorRenderTarget0 = GetTexture("SkyboxProcess", "ColorRenderTarget0");
	RefCountPtr<RHITexture> colorRenderTarget1 = GetTexture("SkyboxProcess", "ColorRenderTarget1");

	mHorDescriptor->SetValue("samplerColor0", colorRenderTarget0, mSampler);
	mHorDescriptor->SetValue("samplerColor1", colorRenderTarget1, mSampler);
	mHorDescriptor->UpdateDescriptor(mHorDescriptorMask);

	mHorColorRenderTarget = ColorRenderTarget::Builder()
		.SetUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)
		.SetStoreOp(VK_ATTACHMENT_STORE_OP_STORE)
		.SetFinalLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
		.SetMultiple(true)
		.Build();

	mHorFrameBuffer = RHIFrameBuffer::Builder()
		.AddRenderTarget(mHorColorRenderTarget)
		.SetRenderPass(mHorRenderPass)
		.Build();



	mVerDescriptor->SetValue("samplerColor0", colorRenderTarget0, mSampler);
	mVerDescriptor->SetValue("samplerColor1", mHorColorRenderTarget, mSampler);
	mVerDescriptor->UpdateDescriptor(mVerDescriptorMask);

	mVerColorRenderTarget = ColorRenderTarget::Builder()
		.SetUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)
		.SetStoreOp(VK_ATTACHMENT_STORE_OP_STORE)
		.SetFinalLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
		.SetMultiple(true)
		.Build(this, "ColorRenderTarget");

	mVerFrameBuffer = RHIFrameBuffer::Builder()
		.AddRenderTarget(mVerColorRenderTarget)
		.SetRenderPass(mVerRenderPass)
		.Build();
}
